import { DomResult } from './types'

interface WatchTextOptions {
  timeout?: number
  checkInterval?: number // 检查间隔，避免过于频繁的检查
}

const DEFAULT_WATCH_TEXT_OPTIONS: Required<WatchTextOptions> = {
  timeout: 10000, // 默认10秒
  checkInterval: 100 // 检查间隔100ms
}

// 创建选择器函数的辅助函数
export const createSelector = (selector: string): (() => Element | null) => {
  return () => document.querySelector(selector)
}

// 元素监听结果接口
interface WatchElementResult {
  success: DomResult
  element?: Element | null
}

// 内部实现：等待元素出现并返回详细结果
const waitForElementInternal = async (
  selectorFn: string | (() => Element | null),
  options: WatchTextOptions = {}
): Promise<WatchElementResult> => {
  const { timeout, checkInterval } = { ...DEFAULT_WATCH_TEXT_OPTIONS, ...options }

  return new Promise((resolve) => {
    // 统一处理选择器函数
    const elementSelector = typeof selectorFn === 'string'
      ? createSelector(selectorFn)
      : selectorFn

    let observer: MutationObserver | null = null
    let intervalId: NodeJS.Timeout | null = null
    const startTime = Date.now()

    // 检查元素的函数
    const checkElement = (): Element | null => {
      return elementSelector()
    }

    // 立即检查一次
    const immediateElement = checkElement()
    if (immediateElement) {
      resolve({
        success: DomResult.SUCCESS,
        element: immediateElement
      })
      return
    }

    // 设置观察器监听DOM变化
    observer = new MutationObserver(() => {
      const element = checkElement()
      if (element) {
        cleanup()
        resolve({
          success: DomResult.SUCCESS,
          element
        })
      }
    })

    // 设置定期检查（作为备选方案，确保不会错过变化）
    intervalId = setInterval(() => {
      const element = checkElement()
      if (element) {
        cleanup()
        resolve({
          success: DomResult.SUCCESS,
          element
        })
        return
      }

      // 检查超时
      if (Date.now() - startTime >= timeout) {
        cleanup()
        resolve({
          success: DomResult.NOT_FOUND,
          element: null
        })
      }
    }, checkInterval)

    // 开始观察
    observer.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: true, // 监听属性变化
    })

    // 设置总超时
    const timeoutId = setTimeout(() => {
      cleanup()
      resolve({
        success: DomResult.NOT_FOUND,
        element: null
      })
    }, timeout)

    // 清理函数
    const cleanup = () => {
      if (observer) {
        observer.disconnect()
        observer = null
      }
      if (intervalId) {
        clearInterval(intervalId)
        intervalId = null
      }
      clearTimeout(timeoutId)
    }

    // 如果Promise被取消，清理资源
    Promise.resolve().then(() => {
      // 确保在微任务中检查，避免竞态条件
    })
  })
}

// 版本1：只返回状态（与现有API保持一致）
export const $watchElement = async (
  selectorFn: string | (() => Element | null),
  options: WatchTextOptions = {}
): Promise<DomResult> => {
  const result = await waitForElementInternal(selectorFn, options)
  return result.success
}

// 版本2：返回节点和状态
export const $watchElementWithNode = async (
  selectorFn: string | (() => Element | null),
  options: WatchTextOptions = {}
): Promise<WatchElementResult> => {
  return waitForElementInternal(selectorFn, options)
}

// 文本监听函数
export const $watchText = async (
  selectorFn: string | (() => Element | null),
  expectedText: string,
  options: WatchTextOptions = {}
): Promise<DomResult> => {
  const { timeout, checkInterval } = { ...DEFAULT_WATCH_TEXT_OPTIONS, ...options }

  return new Promise((resolve) => {
    // 统一处理选择器函数
    const elementSelector = typeof selectorFn === 'string'
      ? createSelector(selectorFn)
      : selectorFn

    let observer: MutationObserver | null = null
    let intervalId: NodeJS.Timeout | null = null
    const startTime = Date.now()

    // 检查文本内容的函数
    const checkTextContent = (): boolean => {
      const element = elementSelector()
      if (!element) {
        return false
      }

      const actualText = element.textContent?.trim() || ''
      return actualText === expectedText
    }

    // 立即检查一次
    if (checkTextContent()) {
      resolve(DomResult.SUCCESS)
      return
    }

    // 设置观察器监听DOM变化
    observer = new MutationObserver(() => {
      if (checkTextContent()) {
        cleanup()
        resolve(DomResult.SUCCESS)
      }
    })

    // 设置定期检查（作为备选方案，确保不会错过变化）
    intervalId = setInterval(() => {
      if (checkTextContent()) {
        cleanup()
        resolve(DomResult.SUCCESS)
        return
      }

      // 检查超时
      if (Date.now() - startTime >= timeout) {
        cleanup()
        resolve(DomResult.NOT_FOUND)
      }
    }, checkInterval)

    // 开始观察
    observer.observe(document.body, {
      childList: true,
      subtree: true,
      characterData: true, // 监听文本内容变化
      attributes: true,    // 监听属性变化（可能影响显示文本）
    })

    // 设置总超时
    const timeoutId = setTimeout(() => {
      cleanup()
      resolve(DomResult.NOT_FOUND)
    }, timeout)

    // 清理函数
    const cleanup = () => {
      if (observer) {
        observer.disconnect()
        observer = null
      }
      if (intervalId) {
        clearInterval(intervalId)
        intervalId = null
      }
      clearTimeout(timeoutId)
    }

    // 如果Promise被取消，清理资源
    Promise.resolve().then(() => {
      // 确保在微任务中检查，避免竞态条件
    })
  })
}

// 增强版的文本监听，支持正则表达式和自定义匹配函数
export const $watchTextAdvanced = async (
  selectorFn: string | (() => Element | null),
  textMatcher: string | RegExp | ((text: string) => boolean),
  options: WatchTextOptions = {}
): Promise<DomResult> => {
  const { timeout, checkInterval } = { ...DEFAULT_WATCH_TEXT_OPTIONS, ...options }

  return new Promise((resolve) => {
    const elementSelector = typeof selectorFn === 'string'
      ? createSelector(selectorFn)
      : selectorFn

    let observer: MutationObserver | null = null
    let intervalId: NodeJS.Timeout | null = null
    const startTime = Date.now()

    // 创建匹配函数
    const createMatcher = (): ((text: string) => boolean) => {
      if (typeof textMatcher === 'string') {
        return (text: string) => text === textMatcher
      } else if (textMatcher instanceof RegExp) {
        return (text: string) => textMatcher.test(text)
      } else {
        return textMatcher
      }
    }

    const matcher = createMatcher()

    // 检查文本内容的函数
    const checkTextContent = (): boolean => {
      const element = elementSelector()
      if (!element) {
        return false
      }

      const actualText = element.textContent?.trim() || ''
      return matcher(actualText)
    }

    // 立即检查一次
    if (checkTextContent()) {
      resolve(DomResult.SUCCESS)
      return
    }

    // 设置观察器
    observer = new MutationObserver(() => {
      if (checkTextContent()) {
        cleanup()
        resolve(DomResult.SUCCESS)
      }
    })

    // 设置定期检查
    intervalId = setInterval(() => {
      if (checkTextContent()) {
        cleanup()
        resolve(DomResult.SUCCESS)
        return
      }

      if (Date.now() - startTime >= timeout) {
        cleanup()
        resolve(DomResult.NOT_FOUND)
      }
    }, checkInterval)

    // 开始观察
    observer.observe(document.body, {
      childList: true,
      subtree: true,
      characterData: true,
      attributes: true,
    })

    // 设置总超时
    const timeoutId = setTimeout(() => {
      cleanup()
      resolve(DomResult.NOT_FOUND)
    }, timeout)

    // 清理函数
    const cleanup = () => {
      if (observer) {
        observer.disconnect()
        observer = null
      }
      if (intervalId) {
        clearInterval(intervalId)
        intervalId = null
      }
      clearTimeout(timeoutId)
    }
  })
}

// 导出新的选项类型和结果类型
export type { WatchElementResult, WatchTextOptions }

